package card

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"mime"
	"mime/multipart"
	"net/http"
	"net/textproto"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/xuri/excelize/v2"
)

const (
	HOST           = "https://syapi.sytechnology.com"
	LLM_OCR        = "http://10.10.13.32:18889/llmparse"
	LLM_OCR2       = "https://newocr-test.syitservice.com/icr/recognize_id_card"
	TOKEN          = "ec5a066a-9c02-4e47-9a98-b9ab907abc58"
	FileName       = "file5.xlsx"
	OutputFileName = "file5_out4.xlsx"
	SheetName      = "Sheet"
	HeaderRowIndex = 1
	MaxConcurrency = 20                   // 设置最大并发数
	MaxRetries     = 3                    // 设置最大重试次数
	RetryDelay     = 1 * time.Millisecond // 设置重试间隔时间
)

// Record 结构体表示 Excel 文件中的一条记录
type Record struct {
	CustomerID         string   // 客户ID
	MemberStatus       string   // 成员身份
	MemberID           string   // 成员ID
	MemberName         string   // 成员名称
	Province           string   // 省
	ProvinceCode       string   // 省code
	City               string   // 市
	CityCode           string   // 市code
	Area               string   // 区
	AreaCode           string   // 区code
	Remaining          string   // 剩余地址
	Address            string   // 地址
	AdminPhotoFront    []string // 管理员正面
	LegalRepPhotoFront []string // 法人正面
	FileId             string   // 名称和成员名称相等的fileId
	Up                 bool     // 身份证正面
}

// 地址信息
type Address struct {
	Province     string
	ProvinceCode string
	City         string
	CityCode     string
	Area         string
	AreaCode     string
	Address      string // 地址
	Remaining    string // 剩余地址
}

// FileResult 结构体表示文件处理结果
type FileResult struct {
	FileName string
	Result   map[string]interface{}
}

// ReadExcel 读取 Excel 文件，并返回包含记录的切片
func ReadExcel() []Record {
	f, err := excelize.OpenFile(filepath.Join("..", FileName))
	if err != nil {
		log.Fatalf("无法打开文件: %v", err)
	}
	defer f.Close()

	rows, err := f.GetRows(SheetName)
	if err != nil {
		log.Fatalf("无法获取行: %v", err)
	}

	// 查找列索引
	colIndices := map[string]int{
		"客户ID":  -1,
		"成员身份":  -1,
		"成员ID":  -1,
		"成员名称":  -1,
		"户籍地-省": -1,
		"户籍地-市": -1,
		"户籍地-区": -1,
		"户籍地":   -1,
		"管理员正面": -1,
		"法人正面":  -1,
	}
	for colIndex, colCell := range rows[HeaderRowIndex-1] {
		if _, ok := colIndices[colCell]; ok {
			colIndices[colCell] = colIndex
		}
	}

	// 解析数据行
	var records []Record
	for _, row := range rows[HeaderRowIndex:] {
		adminPhotoFrontIds := getCellValue(row, colIndices["管理员正面"])
		legalRepPhotoFrontIds := getCellValue(row, colIndices["法人正面"])
		if adminPhotoFrontIds != "" || legalRepPhotoFrontIds != "" {
			record := Record{
				CustomerID:         getCellValue(row, colIndices["客户ID"]),
				MemberStatus:       getCellValue(row, colIndices["成员身份"]),
				MemberID:           getCellValue(row, colIndices["成员ID"]),
				MemberName:         getCellValue(row, colIndices["成员名称"]),
				Province:           getCellValue(row, colIndices["户籍地-省"]),
				City:               getCellValue(row, colIndices["户籍地-市"]),
				Area:               getCellValue(row, colIndices["户籍地-区"]),
				Address:            getCellValue(row, colIndices["户籍地"]),
				AdminPhotoFront:    strings.Split(adminPhotoFrontIds, ","),
				LegalRepPhotoFront: strings.Split(legalRepPhotoFrontIds, ","),
			}
			records = append(records, record)
		}
	}

	return records
}

func downloadAndSaveFile(fileId, outputDir string, sem chan struct{}, wg *sync.WaitGroup) {
	defer wg.Done()
	sem <- struct{}{}        // Block until there's an available slot
	defer func() { <-sem }() // Release the slot

	url := fmt.Sprintf("%s/file/getFile/%s?access_token=%s", HOST, fileId, TOKEN)

	outputPath, err := downloadFileWithRetries(url, outputDir, fileId)
	if err != nil {
		fmt.Println(fmt.Errorf("文件下载错误: %v", err))
	} else {
		// Download successful, calculate and print the file hash
		if newHash, err := calculateFileHash(outputPath); err == nil {
			fmt.Printf("File %s downloaded successfully to %s with hash %s\n", fileId, outputPath, newHash)
		} else {
			fmt.Printf("File %s downloaded successfully to %s but failed to calculate hash: %v\n", fileId, outputPath, err)
		}
	}
}

// WriteFile 并发地下载文件，并将它们保存到指定目录
func WriteFile(list []Record, wg *sync.WaitGroup) {
	outputDir := filepath.Join("..", "pdf")

	// 确保输出目录存在
	if err := os.MkdirAll(outputDir, os.ModePerm); err != nil {
		fmt.Println("Error creating directories:", err)
		return
	}

	sem := make(chan struct{}, MaxConcurrency) // 并发限制

	for _, item := range list {
		allFileIds := append(item.LegalRepPhotoFront, item.AdminPhotoFront...)
		for _, fileId := range allFileIds {
			if fileId != "" {
				wg.Add(1)
				go downloadAndSaveFile(fileId, outputDir, sem, wg)
			}
		}
	}
}

// 计算文件的MD5哈希
func calculateFileHash(filePath string) (string, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return "", fmt.Errorf("error opening file: %v", err)
	}
	defer file.Close()

	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		return "", fmt.Errorf("error calculating hash: %v", err)
	}

	return fmt.Sprintf("%x", hash.Sum(nil)), nil
}

// 带重试逻辑的文件下载函数
func downloadFileWithRetries(url, outputDir, filePhysicalID string) (string, error) {
	for i := 0; i < MaxRetries; i++ {
		outputPath, err := downloadFile(url, outputDir, filePhysicalID)
		if err == nil {
			return outputPath, nil
		}
		fmt.Printf("Attempt #%d: error while downloading file: %v\n", i+1, err)
		time.Sleep(RetryDelay)
	}
	return "", fmt.Errorf("failed to download file after %d retries", MaxRetries)
}

// 文件下载函数
func downloadFile(url, outputDir, fileId string) (string, error) {
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("server returned non-200 status: %d %s", resp.StatusCode, resp.Status)
	}

	contentType := resp.Header.Get("Content-Type")
	ext, err := mime.ExtensionsByType(contentType)
	if err != nil || len(ext) == 0 {
		fmt.Printf("error getting file extension for MIME type %s: %v\n", contentType, err)
		ext = []string{".dat"} // 默认扩展名
	}
	outputPath := filepath.Join(outputDir, fileId+ext[0])

	// 检查文件是否已经存在且大小大于0
	if fileInfo, err := os.Stat(outputPath); err == nil && fileInfo.Size() > 0 {
		// 计算现有文件哈希
		existingHash, err := calculateFileHash(outputPath)
		if err == nil {
			// 验证文件的完整性，如果文件已存在且哈希匹配，跳过下载
			fmt.Printf("File %s already exists and is not empty with hash %s, skipping download.\n", fileId, existingHash)
			return outputPath, nil
		}
	}

	// 写入文件
	outFile, err := os.Create(outputPath)
	if err != nil {
		return "", fmt.Errorf("error while creating file: %v", err)
	}
	defer outFile.Close()

	if _, err := io.Copy(outFile, resp.Body); err != nil {
		return "", fmt.Errorf("error while copying file: %v", err)
	}
	return outputPath, nil
}

func getCellValue(row []string, index int) string {
	if index >= 0 && index < len(row) {
		return row[index]
	}
	return ""
}

// 发送文件请求
func SendRequest(record interface{}, filePath string, deltaX, deltaY int) ([]map[string]interface{}, error) {
	var requestBody bytes.Buffer
	multipartWriter := multipart.NewWriter(&requestBody)

	fileName := filepath.Base(filePath)
	file, err := os.Open(filePath)
	if err != nil {
		return nil, fmt.Errorf("error opening file: %v, %s", err, fileName)
	}
	defer file.Close()

	contentType := "application/octet-stream"
	if strings.HasSuffix(strings.ToLower(fileName), ".pdf") {
		contentType = "application/pdf"
	}

	partHeaders := textproto.MIMEHeader{
		"Content-Disposition": []string{fmt.Sprintf(`form-data; name="file"; filename="%s"`, fileName)},
		"Content-Type":        []string{contentType},
	}
	part, err := multipartWriter.CreatePart(partHeaders)
	if err != nil {
		return nil, fmt.Errorf("error creating form file part: %v, %s", err, fileName)
	}

	if _, err := io.Copy(part, file); err != nil {
		return nil, fmt.Errorf("error copying file to form file: %v, %s", err, fileName)
	}

	questions := `[
        { "name": "name", "description": "姓名:身份证上的名字", "type": "string" },
        { "name": "sex", "description": "性别:身份证上的性别", "type": "string" },
        { "name": "nation", "description": "民族:身份证上的民族", "type": "string" },
        { "name": "birthday", "description": "出生:身份证上的出生日期", "type": "string" },
        { "name": "address", "description": "住址:身份证上的住址", "type": "string" },
        { "name": "cardNumber", "description": "公民身份号码:身份证上的身份证号码", "type": "string" }
    ]`
	_ = multipartWriter.WriteField("questions", questions)
	_ = multipartWriter.WriteField("xPositionDelta", fmt.Sprintf("%d", deltaX))
	_ = multipartWriter.WriteField("yPositionDelta", fmt.Sprintf("%d", deltaY))
	_ = multipartWriter.WriteField("content", "")

	multipartWriter.Close()

	client := &http.Client{
		Timeout: 60 * time.Second,
	}

	// Loop for retrying requests with decreasing delta
	for retries := MaxRetries; retries >= 0; retries-- {
		request, err := http.NewRequest("POST", LLM_OCR, &requestBody)
		if err != nil {
			// If request creation fails, no need to retry, return error immediately
			return nil, fmt.Errorf("error creating request: %v, %s", err, fileName)
		}
		request.Header.Set("Content-Type", multipartWriter.FormDataContentType())
		request.Header.Set("accept", "application/json")

		resp, err := client.Do(request)
		if err != nil {
			fmt.Printf("error sending request: %v, %s\n", err, fileName)
			time.Sleep(RetryDelay) // Wait before retrying
			continue
		}
		defer resp.Body.Close()

		responseData, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Printf("error reading response body: %v, %s\n", err, fileName)
			time.Sleep(RetryDelay)
			continue
		}

		if resp.StatusCode >= 400 {
			fmt.Printf("error response from server: %s, %d\n", string(responseData), resp.StatusCode)
			time.Sleep(RetryDelay)
			continue
		}

		var results []map[string]interface{}
		err = json.Unmarshal(responseData, &results)
		if err != nil {
			fmt.Printf("error unmarshalling response body: %v, %s\n", err, fileName)
			time.Sleep(RetryDelay)
			continue
		}

		if len(results) == 0 && retries > 0 {
			fmt.Printf("No results found, retrying with deltaX: %d, deltaY: %d\n", deltaY, deltaY)
			deltaX -= 20
			deltaY -= 20
			time.Sleep(RetryDelay) // Wait before retrying
			continue
		}

		return results, nil
	}

	// If we exhaust all retries, return error
	return nil, fmt.Errorf("failed to process file %s after %d retries", fileName, MaxRetries)
}

func SendRequest2(record interface{}, filePath string) ([]map[string]interface{}, error) {
	var requestBody bytes.Buffer
	multipartWriter := multipart.NewWriter(&requestBody)

	fileName := filepath.Base(filePath)
	file, err := os.Open(filePath)
	if err != nil {
		return nil, fmt.Errorf("error opening file: %v, %s", err, fileName)
	}
	defer file.Close()

	// Set the form headers and body for the file
	partHeaders := textproto.MIMEHeader{
		"Content-Disposition": []string{fmt.Sprintf(`form-data; name="file"; filename="%s"`, fileName)},
		"Content-Type":        []string{"application/octet-stream"},
	}
	part, err := multipartWriter.CreatePart(partHeaders)
	if err != nil {
		return nil, fmt.Errorf("error creating form file part: %v, %s", err, fileName)
	}

	if _, err := io.Copy(part, file); err != nil {
		return nil, fmt.Errorf("error copying file to form file: %v, %s", err, fileName)
	}

	// Write other form fields
	_ = multipartWriter.WriteField("crop_image", "1")
	_ = multipartWriter.WriteField("head_portrait", "1")
	_ = multipartWriter.WriteField("id_number_image", "1")
	_ = multipartWriter.WriteField("recognize_mode", "1")

	err = multipartWriter.Close()
	if err != nil {
		return nil, fmt.Errorf("error closing multipart writer: %v", err)
	}

	client := &http.Client{Timeout: 60 * time.Second}

	for retries := MaxRetries; retries >= 0; retries-- {
		request, err := http.NewRequest("POST", LLM_OCR2, &requestBody)
		if err != nil {
			return nil, fmt.Errorf("error creating request: %v, %s", err, fileName)
		}

		request.Header.Set("Content-Type", multipartWriter.FormDataContentType())
		request.Header.Set("Accept", "*/*")
		request.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")

		resp, err := client.Do(request)
		if err != nil {
			fmt.Printf("error sending request: %v, %s\n", err, fileName)
			time.Sleep(RetryDelay)
			continue
		}
		defer resp.Body.Close()

		responseData, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Printf("error reading response body: %v, %s\n", err, fileName)
			time.Sleep(RetryDelay)
			continue
		}

		if resp.StatusCode >= 400 {
			return nil, fmt.Errorf("error response from server: %s, %d", string(responseData), resp.StatusCode)
		}

		var result map[string]interface{}
		err = json.Unmarshal(responseData, &result)
		if err != nil {
			fmt.Printf("error unmarshalling response body: %v, %s\n", err, fileName)
			time.Sleep(RetryDelay)
			continue
		}

		return []map[string]interface{}{result}, nil
	}

	return nil, fmt.Errorf("failed to process file %s after %d retries", fileName, MaxRetries)
}

// 批量发送请求
func SendRequestForFilesInDir() ([]FileResult, error) {
	outputDir := filepath.Join("..", "pdf")
	files, err := os.ReadDir(outputDir)
	if err != nil {
		return nil, fmt.Errorf("error reading directory: %v", err)
	}

	sem := make(chan struct{}, MaxConcurrency)
	var wg sync.WaitGroup
	var fileResults []FileResult
	var mu sync.Mutex // 定义一个互斥锁
	// count := 0        // 定义一个计数器

	for _, file := range files {
		if file.IsDir() {
			continue // 跳过子目录
		}

		// test
		// allowedFiles := map[string]bool{
		// 	"3878224753835773952.pdf": true,
		// 	"1235506858313228290.pdf": true,
		// }
		// if !allowedFiles[file.Name()] {
		// 	continue
		// }

		wg.Add(1)
		go func(file os.DirEntry) {
			defer wg.Done()
			sem <- struct{}{}        // 阻塞直到有空闲的并发槽位
			defer func() { <-sem }() // 释放并发槽位

			filePath := filepath.Join(outputDir, file.Name())
			record := Record{} // 可以在这里填充适当的记录信息

			// results, err := SendRequest(record, filePath, 1000, 1000)
			results, err := SendRequest2(record, filePath)
			fmt.Println("results File:", file.Name())
			if err != nil || len(results) == 0 {
				fmt.Println("Error sending request:", err)
			} else {
				mu.Lock() // 上锁
				fileResults = append(fileResults, FileResult{
					FileName: file.Name(),
					Result:   results[0],
				})
				mu.Unlock() // 解锁
			}
		}(file)

		// count++
		// if count >= 100 {
		// 	break
		// }
	}

	wg.Wait()
	return fileResults, nil
}

// containsString 检查 map 中的某个键对应的值是否包含特定子字符串
func ContainsString(data map[string]interface{}, keys []string, substr string) bool {
	for _, key := range keys {
		if value, ok := data[key]; ok {
			if strValue, isString := value.(string); isString {
				if strings.Contains(substr, strValue) || strings.Contains(strValue, substr) {
					return true
				}
			}
		}
	}
	return false
}

func ReadAddressExcelFile() ([][]string, map[string]int, error) {
	f, err := excelize.OpenFile(filepath.Join("..", "baidu_20230425.xlsx"))
	if err != nil {
		return nil, nil, fmt.Errorf("无法打开文件: %v", err)
	}
	defer f.Close()

	rows, err := f.GetRows("Sheet1")
	if err != nil {
		return nil, nil, fmt.Errorf("无法获取行: %v", err)
	}

	// 查找列索引
	colIndices := map[string]int{
		"省份名称": -1,
		"城市名称": -1,
		"区县名称": -1,
	}
	headerRowIndex := 1
	for colIndex, colCell := range rows[headerRowIndex-1] {
		if _, ok := colIndices[colCell]; ok {
			colIndices[colCell] = colIndex
		}
	}

	for k, v := range colIndices {
		if v == -1 {
			return nil, nil, fmt.Errorf("未找到列: %s", k)
		}
	}

	return rows, colIndices, nil
}

// TrimPrefixes 移除字符串中的多个前缀
func TrimPrefixes(s string, prefixes ...string) string {
	for _, prefix := range prefixes {
		s = strings.TrimPrefix(s, prefix)
	}
	return s
}

func ReArea(name string, rows [][]string, colIndices map[string]int) Address {
	// 定义正则表达式模式
	pattern := `^((?:.*?(?:省|自治区|直辖市|特别行政区|北京市|上海市|天津市|重庆市|广西|内蒙古|宁夏|新疆|西藏)))?(.*?(?:自治州|地区|盟|市|区))?(.*?(?:市|区|县|自治县|旗|自治旗|林区|镇|乡|村))?.*$`

	// 编译正则表达式
	reg := regexp.MustCompile(pattern)

	new_name := strings.ReplaceAll(name, " ", "")
	new_name = strings.ReplaceAll(new_name, "　", "")
	new_name = strings.ReplaceAll(new_name, ":", "")
	new_name = strings.ReplaceAll(new_name, "：", "")
	if strings.HasPrefix(new_name, "住址") || strings.HasPrefix(new_name, "地址") || strings.HasPrefix(new_name, "佳址") {
		new_name = strings.Replace(new_name, "住址", "", 1)
		new_name = strings.Replace(new_name, "地址", "", 1)
		new_name = strings.Replace(new_name, "佳址", "", 1)
	}
	// 匹配正则表达式
	matches := reg.FindStringSubmatch(new_name)

	var address Address
	if len(matches) > 3 {
		province := matches[1]
		city := matches[2]
		area := matches[3]
		fmt.Printf("%s - %s - %s = %s\n", province, city, area, new_name)

		// 处理直辖市的逻辑
		if province == "北京市" || province == "上海市" || province == "重庆市" || province == "天津市" {
			area = city
			city = province
		}

		// 处理自治区
		if province == "内蒙古" {
			province = "内蒙古自治区"
		} else if province == "西藏" {
			province = "西藏自治区"
		} else if province == "新疆" {
			province = "新疆维吾尔自治区"
		} else if province == "宁夏" {
			province = "宁夏回族自治区"
		} else if province == "广西" {
			province = "广西壮族自治区"
		}

		// 解析数据行，找到与匹配地址对应的省市区代码
		for _, row := range rows[1:] {
			rowProvince := getCellValue(row, colIndices["省份名称"])
			rowProvinceCode := getCellValue(row, colIndices["省份名称"]+1)
			rowCity := getCellValue(row, colIndices["城市名称"])
			rowCityCode := getCellValue(row, colIndices["城市名称"]+1)
			rowArea := getCellValue(row, colIndices["区县名称"])
			rowAreaCode := getCellValue(row, colIndices["区县名称"]+1)

			if (province == rowProvince && city == rowCity && area == rowArea) ||
				(province == "" && city == rowCity && area == rowArea) ||
				(province == rowProvince && city == "" && area == rowArea) ||
				(province == rowProvince && city == rowArea) {

				// 逐个前缀处理，依次去掉省、市、区
				remaining := TrimPrefixes(new_name, rowProvince, rowCity, rowArea)

				address = Address{
					Province:     rowProvince,
					ProvinceCode: rowProvinceCode,
					City:         rowCity,
					CityCode:     rowCityCode,
					Area:         rowArea,
					AreaCode:     rowAreaCode,
					Remaining:    remaining,
				}
				break
			}
		}
	}
	return address
}

func WriteExcel(list []Record) {
	f, err := excelize.OpenFile("../" + FileName)
	if err != nil {
		fmt.Println("Error opening Excel file:", err)
		return
	}
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println("Error closing Excel file:", err)
		}
	}()

	// 获取工作表中所有的行
	rows, err := f.GetRows(SheetName)
	if err != nil {
		fmt.Println("Error reading rows:", err)
		return
	}

	// 查找列索引
	colIndices := map[string]int{
		"客户ID":    -1,
		"成员身份":    -1,
		"成员ID":    -1,
		"成员名称":    -1,
		"户籍地-省":   -1,
		"省code":   -1,
		"户籍地-市":   -1,
		"市code":   -1,
		"户籍地-区":   -1,
		"区code":   -1,
		"剩余地址":    -1,
		"户籍地":     -1,
		"管理员正面":   -1,
		"法人正面":    -1,
		"有效法人正面":  -1,
		"有效管理员正面": -1,
	}
	for colIndex, colCell := range rows[HeaderRowIndex-1] {
		if _, ok := colIndices[colCell]; ok {
			colIndices[colCell] = colIndex
		}
	}

	// 记录已处理的成员ID
	processedMemberIDs := make(map[string]bool)

	// 遍历list并更新数据
	for _, info := range list {
		if _, alreadyProcessed := processedMemberIDs[info.MemberID]; alreadyProcessed {
			continue // 已处理过的成员ID跳过
		}

		for rowIndex, row := range rows {
			if rowIndex < HeaderRowIndex { // 跳过前两行（第一行和标题行）
				continue
			}

			// 假设根据“成员ID”进行匹配
			if colIndices["成员ID"] != -1 && row[colIndices["成员ID"]] == info.MemberID {
				if colIndices["客户ID"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["客户ID"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.CustomerID)
				}
				if colIndices["成员身份"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["成员身份"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.MemberStatus)
				}
				if colIndices["成员名称"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["成员名称"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.MemberName)
				}
				if colIndices["户籍地-省"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["户籍地-省"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.Province)
				}
				if colIndices["省code"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["省code"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.ProvinceCode)
				}
				if colIndices["户籍地-市"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["户籍地-市"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.City)
				}
				if colIndices["市code"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["市code"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.CityCode)
				}
				if colIndices["户籍地-区"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["户籍地-区"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.Area)
				}
				if colIndices["区code"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["区code"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.AreaCode)
				}
				if colIndices["剩余地址"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["剩余地址"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.Remaining)
				}
				if colIndices["户籍地"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["户籍地"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.Address)
				}
				if colIndices["管理员正面"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["管理员正面"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, strings.Join(info.AdminPhotoFront, ","))
				}
				if colIndices["法人正面"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["法人正面"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, strings.Join(info.LegalRepPhotoFront, ","))
				}
				if info.MemberStatus == "LEGALPERSON" && colIndices["有效法人正面"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["有效法人正面"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.FileId)
				}
				if info.MemberStatus == "ADMIN" && colIndices["有效管理员正面"] != -1 {
					cell, _ := excelize.CoordinatesToCellName(colIndices["有效管理员正面"]+1, rowIndex+1)
					f.SetCellValue(SheetName, cell, info.FileId)
				}

				// 记录已处理的成员ID
				processedMemberIDs[info.MemberID] = true
				break
			}
		}
	}

	// 保存文件
	if err := f.SaveAs("../" + OutputFileName); err != nil {
		fmt.Println("Error saving Excel file:", err)
	}
}
